package com.explorx.sns.puma.im.core.controller;

import com.explorex.puma.common.enums.ConvTypeEnum;
import com.explorex.puma.common.enums.VisibleEnum;
import com.explorex.puma.common.utils.SnowflakeIdWorker;
import com.explorx.sns.puma.im.core.chat.ConversationService;
import com.explorx.sns.puma.im.core.chat.GroupManager;
import com.explorx.sns.puma.im.core.chat.UserInfoDomainService;
import com.explorx.sns.puma.im.core.chat.consts.GroupFiledPrivilegeEnum;
import com.explorx.sns.puma.im.core.chat.consts.GroupMemberRoleEnum;
import com.explorx.sns.puma.im.core.chat.consts.GroupMemberStatusEnum;
import com.explorx.sns.puma.im.core.chat.consts.GroupStatusEnum;
import com.explorx.sns.puma.im.core.chat.model.*;
import com.explorx.sns.puma.im.core.common.exceptions.BizException;
import com.explorx.sns.puma.im.core.dal.dao.GroupBaseInfoEntityMapper;
import com.explorx.sns.puma.im.core.dal.dao.GroupMemberEntityMapper;
import com.explorx.sns.puma.im.core.dal.entity.GroupBaseInfoEntity;
import com.explorx.sns.puma.im.core.dal.entity.GroupBaseInfoEntityExample;
import com.explorx.sns.puma.im.core.dal.entity.GroupMemberEntity;
import com.explorx.sns.puma.im.core.dal.entity.GroupMemberEntityExample;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Service
public class GroupManagerImpl implements GroupManager {

    @Resource
    private UserInfoDomainService userInfoDomainService;

    @Resource
    private ConversationService conversationService;

    @Resource
    private GroupBaseInfoEntityMapper baseInfoEntityMapper;

    @Resource
    private GroupMemberEntityMapper groupMemberEntityMapper;

    @Override
    public UserConvBase createGroup(CreateGroupDto createGroupDto) throws BizException {
        GroupBaseInfoEntity entity = new GroupBaseInfoEntity();
        final long groupId = SnowflakeIdWorker.nextId();
        entity.setGroupId(groupId);
        entity.setCreateTime(new Date());
        entity.setCreatorId(createGroupDto.getCreatorId());
        entity.setOwnerId(createGroupDto.getCreatorId());
        entity.setGroupName(createGroupDto.getGroupName());
        entity.setAvatar(buildGroupAvatar(createGroupDto.getCreatorId(), createGroupDto.getMembers()));
        entity.setVisible((byte) VisibleEnum.PUBLIC.getValue());
        entity.setStatus(GroupStatusEnum.NORMAL.getValue());
        entity.setMemberCnt(1);
        final int insert = baseInfoEntityMapper.insert(entity);
        if (insert <= 0) {
            return null;
        }
        JoinGroupDto joinGroupDto = new JoinGroupDto();
        joinGroupDto.setGroupId(groupId);
        joinGroupDto.setUserId(createGroupDto.getCreatorId());
        joinGroup(joinGroupDto, GroupMemberRoleEnum.OWNER);
        return UserConvBase.builder()
                .convType(ConvTypeEnum.GROUP.getValue())
                .cid(0L).senderId(createGroupDto.getCreatorId())
                .partnerId(groupId).build();
    }

    private String buildGroupAvatar(Long creatorId, List<Long> memberIds) {



        return "";
    }

    @Override
    public boolean joinGroup(JoinGroupDto joinGroupDto, GroupMemberRoleEnum roleEnum) throws BizException {

        GroupBaseInfoEntityExample groupBaseInfoExample = new GroupBaseInfoEntityExample();
        groupBaseInfoExample.createCriteria()
                .andStatusNotEqualTo(GroupStatusEnum.DISMISS.getValue())
                .andGroupIdEqualTo(joinGroupDto.getGroupId());
        final List<GroupBaseInfoEntity> groupBaseInfoEntities = baseInfoEntityMapper.selectByExample(groupBaseInfoExample);

        if (CollectionUtils.isEmpty(groupBaseInfoEntities)) {
            throw new BizException("群不存在", -1, "群不存在");
        }
        assert groupBaseInfoEntities.size() == 1;
        final GroupBaseInfoEntity groupBaseInfo = groupBaseInfoEntities.get(0);
        if (isInGroup(joinGroupDto.getGroupId(), joinGroupDto.getUserId())) {
            throw new BizException("已加入群聊", -1, "已加入群聊");
        }
        final UserInfoModel userInfo = userInfoDomainService.getUserInfo(joinGroupDto.getUserId());
        GroupMemberEntity groupMemberEntity = new GroupMemberEntity();
        groupMemberEntity.setGroupId(groupBaseInfo.getGroupId());
        groupMemberEntity.setCreateTime(new Date());
        groupMemberEntity.setMemberAvatar(userInfo.getAvatar());
        groupMemberEntity.setUpdateTime(new Date());
        groupMemberEntity.setStatus(GroupStatusEnum.NORMAL.getValue());
        groupMemberEntity.setRole(roleEnum.getValue());
        groupMemberEntity.setUserId(joinGroupDto.getUserId());
        final int insert = groupMemberEntityMapper.insert(groupMemberEntity);
        if (insert > 0) {
            groupBaseInfo.setMemberCnt(Optional.ofNullable(groupBaseInfo.getMemberCnt()).orElse(0) + 1);
            baseInfoEntityMapper.updateByPrimaryKeySelective(groupBaseInfo);
        }
        return false;
    }

    private boolean isInGroup(Long groupId, Long userId) {
        GroupMemberEntityExample groupMemberEntityExample = new GroupMemberEntityExample();
        groupMemberEntityExample.createCriteria()
                .andUserIdEqualTo(userId)
                .andStatusLessThan(GroupMemberStatusEnum.MUTE.getValue())
                .andGroupIdEqualTo(groupId);
        final List<GroupMemberEntity> groupMemberEntities = groupMemberEntityMapper.selectByExample(groupMemberEntityExample);
        return !CollectionUtils.isEmpty(groupMemberEntities);
    }

    @Override
    public void leaveGroup(LeaveGroupDto leaveGroupDto) throws BizException {
        if (!isInGroup(leaveGroupDto.getGroupId(), leaveGroupDto.getUserId())) {
            throw new BizException("不在群中", -1, "不在群中");
        }
        GroupMemberEntity entity = new GroupMemberEntity();
        entity.setStatus(GroupMemberStatusEnum.LEAVE.getValue());
        GroupMemberEntityExample example = new GroupMemberEntityExample();
        example.createCriteria()
                .andGroupIdEqualTo(leaveGroupDto
                        .getGroupId())
                .andUserIdEqualTo(leaveGroupDto.getUserId());
        final int i = groupMemberEntityMapper.updateByExampleSelective(entity, example);
    }

    @Override
    public void dismissGroup(DismissGroup dismissGroup) throws BizException {
        // 检查权限
        GroupMemberEntityExample groupMemberEntityExample = new GroupMemberEntityExample();
        groupMemberEntityExample.createCriteria().andGroupIdEqualTo(dismissGroup.getGroupId()).andUserIdEqualTo(dismissGroup.getUserId());
        final List<GroupMemberEntity> groupMemberEntities = groupMemberEntityMapper.selectByExample(groupMemberEntityExample);

        if (CollectionUtils.isEmpty(groupMemberEntities)) {
            throw new BizException("不在群中", -1, "不在群中");
        }
        assert groupMemberEntities.size() == 1;
        final GroupMemberEntity groupMemberEntity = groupMemberEntities.get(0);
        if (groupMemberEntity.getRole() != GroupMemberRoleEnum.MANAGER.getValue()
                && groupMemberEntity.getRole() != GroupMemberRoleEnum.OWNER.getValue()) {
            throw new BizException("无操作权限", -1, "无操作权限");
        }
        // 操作解除
        GroupBaseInfoEntity groupBaseInfo = new GroupBaseInfoEntity();
        groupBaseInfo.setStatus((byte) GroupStatusEnum.DISMISS.getValue());
        GroupBaseInfoEntityExample example = new GroupBaseInfoEntityExample();
        example.createCriteria().andGroupIdEqualTo(dismissGroup.getGroupId());
        baseInfoEntityMapper.updateByExampleSelective(groupBaseInfo, example);
    }

    @Override
    public List<GroupMemberBo> getGroupMembers(Long userId, Long groupId) throws BizException {

        GroupMemberEntityExample groupMemberEntityExample = new GroupMemberEntityExample();
        groupMemberEntityExample.createCriteria()
                .andUserIdEqualTo(userId)
                .andStatusLessThan(GroupMemberStatusEnum.MUTE.getValue())
                .andGroupIdEqualTo(groupId);
        final List<GroupMemberEntity> groupMemberEntities = groupMemberEntityMapper.selectByExample(groupMemberEntityExample);
        if (CollectionUtils.isEmpty(groupMemberEntities)) {
            throw new BizException("不在群中", -1, "不在群中");
        }

        groupMemberEntityExample.clear();
        groupMemberEntityExample.createCriteria()
                .andStatusLessThan(GroupMemberStatusEnum.MUTE.getValue())
                .andGroupIdEqualTo(groupId);
        final List<GroupMemberEntity> allGroupMemberEntities = groupMemberEntityMapper.selectByExample(groupMemberEntityExample);
        return allGroupMemberEntities.stream().map(ele -> GroupMemberBo.builder().groupId(groupId)
                .groupRemark(ele.getGroupRemark())
                .nickName(ele.getNickName())
                .avatar(ele.getMemberAvatar())
                .status(ele.getStatus())
                .userId(ele.getUserId())
                .role(ele.getRole()).build()).collect(Collectors.toList());
    }

    @Override
    public GroupBaseInfo getGroupBaseInfo(Long userId, Long groupId) {
        GroupBaseInfoEntityExample groupBaseInfoExample = new GroupBaseInfoEntityExample();
        groupBaseInfoExample.createCriteria().andGroupIdEqualTo(groupId);
        final List<GroupBaseInfoEntity> groupBaseInfoEntities = baseInfoEntityMapper.selectByExample(groupBaseInfoExample);

        if (CollectionUtils.isEmpty(groupBaseInfoEntities)) {
            return null;
        }
        assert groupBaseInfoEntities.size() == 1;
        final GroupBaseInfoEntity groupBaseInfo = groupBaseInfoEntities.get(0);
        GroupMemberEntityExample groupMemberEntityExample = new GroupMemberEntityExample();
        groupMemberEntityExample.createCriteria().andGroupIdEqualTo(groupId).andUserIdEqualTo(userId);
        final List<GroupMemberEntity> groupMemberEntities = groupMemberEntityMapper.selectByExample(groupMemberEntityExample);
        if (CollectionUtils.isEmpty(groupMemberEntities)) {
            return null;
        }

        final GroupMemberEntity groupMemberInfo = groupMemberEntities.get(0);
        return GroupBaseInfo.builder()
                .groupName(groupBaseInfo.getGroupName())
                .groupDesc(groupBaseInfo.getGroupDesc())
                .nickName(groupMemberInfo.getNickName())
                .groupAvatar(groupBaseInfo.getAvatar())
                .groupRemark(groupMemberInfo.getGroupRemark())
                .backgroundUrl(groupMemberInfo.getBackgroundUrl())
                .memberCnt(groupBaseInfo.getMemberCnt())
                .creatorId(groupBaseInfo.getCreatorId())
                .qrcode(groupBaseInfo.getQrcode())
                .build();
    }

    @Override
    public boolean editGroupAttribute(EditGroupAttribute editGroupAttribute) throws BizException {
        // 检查权限
        GroupMemberEntityExample groupMemberEntityExample = new GroupMemberEntityExample();
        groupMemberEntityExample.createCriteria()
                .andUserIdEqualTo(editGroupAttribute.getUserId())
                .andStatusLessThan(GroupMemberStatusEnum.MUTE.getValue())
                .andGroupIdEqualTo(editGroupAttribute.getGroupId());
        final List<GroupMemberEntity> groupMemberEntities = groupMemberEntityMapper.selectByExample(groupMemberEntityExample);

        if (CollectionUtils.isEmpty(groupMemberEntities)) {
            throw new BizException("不在群中", -1, "不在群中");
        }
        assert groupMemberEntities.size() == 1;
        final GroupMemberEntity groupMemberEntity = groupMemberEntities.get(0);
        final GroupFiledPrivilegeEnum byId = GroupFiledPrivilegeEnum.findById(editGroupAttribute.getAttributeId());

        if (byId == GroupFiledPrivilegeEnum.UNKONWN || byId.getMinRoleNeed().getValue() > groupMemberEntity.getRole()) {
            throw new BizException("无权限修改", -1, "无权限修改");
        }
        // 操作解除
        GroupBaseInfoEntity groupBaseInfo = new GroupBaseInfoEntity();
        GroupBaseInfoEntityExample example = new GroupBaseInfoEntityExample();
        GroupMemberEntity groupMember = new GroupMemberEntity();
        groupMemberEntityExample.clear();

        switch (byId) {
            case GROUP_NAME:
                groupBaseInfo.setGroupName(editGroupAttribute.getAttributeValue());
                example.createCriteria().andGroupIdEqualTo(editGroupAttribute.getGroupId());
                baseInfoEntityMapper.updateByExampleSelective(groupBaseInfo, example);
                break;
            case GROUP_NOTICE:
                groupBaseInfo.setGroupNotice(editGroupAttribute.getAttributeValue());
                example.createCriteria().andGroupIdEqualTo(editGroupAttribute.getGroupId());
                baseInfoEntityMapper.updateByExampleSelective(groupBaseInfo, example);
                break;
            case GROUP_REMARK:
                groupMember.setGroupRemark(editGroupAttribute.getAttributeValue());
                groupMemberEntityExample.createCriteria()
                        .andGroupIdEqualTo(editGroupAttribute.getGroupId())
                        .andUserIdEqualTo(editGroupAttribute.getUserId());
                groupMemberEntityMapper.updateByExampleSelective(groupMember, groupMemberEntityExample);
                break;
            case GROUP_NICK_NAME:
                groupMember.setNickName(editGroupAttribute.getAttributeValue());
                groupMemberEntityExample.createCriteria()
                        .andGroupIdEqualTo(editGroupAttribute.getGroupId())
                        .andUserIdEqualTo(editGroupAttribute.getUserId());
                groupMemberEntityMapper.updateByExampleSelective(groupMember, groupMemberEntityExample);
                break;
            case UNKONWN:
                throw new BizException("非法参数", -1, "非法参数");
        }
        return false;
    }

    @Override
    public List<GroupBaseInfo> getGroupRecommend(Long uid) {
        GroupBaseInfoEntityExample groupBaseInfoExample = new GroupBaseInfoEntityExample();
        groupBaseInfoExample.createCriteria().andStatusEqualTo(GroupStatusEnum.NORMAL.getValue());
        final List<GroupBaseInfoEntity> groupBaseInfoEntities = baseInfoEntityMapper.selectByExample(groupBaseInfoExample);
        if (CollectionUtils.isEmpty(groupBaseInfoEntities)) {
            return Collections.EMPTY_LIST;
        }
        List<GroupBaseInfo> result = Lists.newArrayList();
        for (GroupBaseInfoEntity groupBaseInfoEntity : groupBaseInfoEntities) {

            result.add(GroupBaseInfo.builder()
                    .groupName(groupBaseInfoEntity.getGroupName())
                    .groupDesc(groupBaseInfoEntity.getGroupDesc())
                    .groupAvatar(groupBaseInfoEntity.getAvatar())
                    .memberCnt(groupBaseInfoEntity.getMemberCnt())
                    .creatorId(groupBaseInfoEntity.getCreatorId())
                    .qrcode(groupBaseInfoEntity.getQrcode())
                    .build());
        }
        return result;
    }

    @Override
    public List<GroupBaseInfo> queryUserGroups(Long uid) {

        GroupMemberEntityExample groupMemberEntityExample = new GroupMemberEntityExample();
        groupMemberEntityExample.createCriteria().andUserIdEqualTo(uid).andStatusEqualTo(GroupStatusEnum.NORMAL.getValue());
        final List<GroupMemberEntity> groupMemberEntities = groupMemberEntityMapper.selectByExample(groupMemberEntityExample);

        if(CollectionUtils.isEmpty(groupMemberEntities)){
            return Collections.emptyList();
        }

        final List<Long> groupIds = groupMemberEntities.stream().map(GroupMemberEntity::getGroupId).collect(Collectors.toList());

        GroupBaseInfoEntityExample groupBaseInfoExample = new GroupBaseInfoEntityExample();
        groupBaseInfoExample.createCriteria()
                .andStatusNotEqualTo(GroupStatusEnum.DISMISS.getValue())
                .andGroupIdIn(groupIds);
        final List<GroupBaseInfoEntity> groupBaseInfoEntities = baseInfoEntityMapper.selectByExample(groupBaseInfoExample);
        List<GroupBaseInfo> result = Lists.newArrayList();
        for (GroupBaseInfoEntity groupBaseInfoEntity : groupBaseInfoEntities) {

            result.add(GroupBaseInfo.builder()
                    .groupName(groupBaseInfoEntity.getGroupName())
                    .groupDesc(groupBaseInfoEntity.getGroupDesc())
                    .groupId(groupBaseInfoEntity.getGroupId())
                    .groupAvatar(groupBaseInfoEntity.getAvatar())
                    .memberCnt(groupBaseInfoEntity.getMemberCnt())
                    .creatorId(groupBaseInfoEntity.getCreatorId())
                    .qrcode(groupBaseInfoEntity.getQrcode())
                    .build());
        }
        return result;
    }
}
